<?php

namespace App\Service;

use App\Common\Model\ShopAccount;
use App\Model\Btree;
use App\Model\Setting;
use App\Traits\ErrorTrait;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class TouchService
{
    use ErrorTrait;
    /**
     * 获取用户量碰信息
     * @param int $uid
     * @return array
     */
    public function getTouchInfo(int $uid) : array
    {
//        $yeterday  = mktime(0, 0, 0, date("m"), date("d") - 1, date("Y"));
        $today = strtotime(date('Y-m-d'));
        $btreeModel = new Btree();
        $user = $btreeModel->where('uid', $uid)->first();
        // 统计左区销售额
        $lsale = $user ? $user->lsale : 0;
        // 统计右区销售额
        $rsale = $user ? $user->rsale : 0;
        // 累计完成量碰
        $totalTouchBonus = DB::table('money_report')->where('uid', $uid)->where('status', 1)->where('types', 4)->sum('amount');
        // 昨日量碰收益
        $yesTouchBonus = DB::table('money_report')->where('uid', $uid)->where('status', 1)->where('types', 4)->where('create_time', '>', $today)->sum('amount');
        return [
            'lzone_day_sale' => $lsale,
            'rzone_day_sale' => $rsale,
            'day_bonus' => $totalTouchBonus,
            'yes_bonus' => $yesTouchBonus,
            'total_bonus' => $totalTouchBonus
        ];
    }

    /**
     * 获取用户左右区销售信息
     * @param int $uid
     * @param int $year
     * @return array
     */
    public function getSalesInfo(int $uid, int $year) : array
    {
        $btreeModel = new Btree();
        // 生成月份时间戳数组
        $monthArr = [];
        for ($i = 1; $i <= 13; ++$i) {
            $monthArr[] = mktime(24, 0, 0, $i, 0, $year);
        }
        // 统计每月左右区销售额
        $monthSales = [];
        $lyearsale = 0;
        $ryearsale = 0;
        for ($k = 1; $k <= 12; ++$k) {
            $lmonthsale = DB::table('sales')->where([
                ['uid', '=', $uid],
                ['zone', '=', 1],
                ['create_time', '>=', $monthArr[$k - 1]],
                ['create_time', '<', $monthArr[$k]]
            ])->sum('sale');
            $rmonthsale = DB::table('sales')->where([
                ['uid', '=', $uid],
                ['zone', '=', 2],
                ['create_time', '>=', $monthArr[$k - 1]],
                ['create_time', '<', $monthArr[$k]]
            ])->sum('sale');
            $lyearsale += $lmonthsale;
            $ryearsale += $rmonthsale;
            $monthSales[] = [
                'month' => $k,
                'lzone_month_sale' => $lmonthsale,
                'rzone_month_sale' => $rmonthsale
            ];
        }
        return [
            'lzone_year_sale' => $lyearsale,
            'rzone_year_sale' => $ryearsale,
            'year' => $year,
            'month_sales' => $monthSales
        ];
    }

    /**
     * 统计销售额
     * @param array $zone  下级id数组
     * @param int $beginTime
     * @param int $endTime
     * @return mixed
     */
    public function aggregateSales($zone, int $beginTime = 0, int $endTime = 0)
    {
        if (!$endTime) {
            $endTime = 999999999999;
        }
        $sale = 0;
        foreach ($zone as $uid) {
            $payRecords = DB::table('pay')->leftJoin('btrees', 'btrees.uid', '=', 'pay.uid')
                ->where('pay.uid', $uid)->where('pay.status', 1)
                ->select('pay.pay_time', 'btrees.create_time', 'pay.money')
                ->get();
            foreach ($payRecords as $payRecord) {
//                $createTime = date('ymd', $payRecord->create_time);
//                $payTime = date('ymd', $payRecord->pay_time);
                if ($payRecord->pay_time <= $payRecord->create_time) { // 如果先消费再建点
                    $compareTime = $payRecord->create_time;
                } else {  // 建点后的消费
                    $compareTime = $payRecord->pay_time;
                }
                if ($compareTime >= $beginTime && $compareTime < $endTime) {
                    $sale += $payRecord->money;
                }
            }

        }
        return $sale;
    }

    /**
     * 获取左区或右区每日销售额统计
     * @param int $uid
     * @param int $year
     * @param int $month
     * @param int $day
     * @param string $zone
     * @param int $start
     * @param int $count
     * @return array
     */
    public function getDaySale(int $uid, int $year, int $month, int $day, string $zone, int $start, int $count)
    {
        $btreeModel = new Btree();
        $return = [];
        // 判断当月有多少天
        $days = date("d", mktime(23, 59, 59, $month + 1, 0, $year));
        if ($day > 0 && $day <= $days) {
            $dayArr = [$day, $day];
            $return['rest'] = 0;
        } elseif ($start + $count < $days) {
            $dayArr = [$start + 1, $start + $count];
            $return['rest'] = $days - $start - $count;
        } else {
            if ($start < $days) {
                $dayArr = [$start + 1, $days];
                $return['rest'] = 0;
            } else {
                return ['list' => [], 'rest' => 0];
            }
        }
        // 统计该天的销售记录
        for ($i = $dayArr[0]; $i <= $dayArr[1]; ++$i) {
            $res['date'] = $month . '月' . $i . '日';
            $today = strtotime($year.'-'.$month.'-'.$i);
            $tomorrow = mktime(0, 0, 0, $month, $i + 1, $year);
            if ($zone == 'l') { // 左区
                $zone = 1;
            } elseif ($zone == 'r') { // 右区
                $zone = 2;
            }
            $persons = DB::table('sales')->leftJoin('shop_accounts', 'sales.pro_uid', '=', 'shop_accounts.uid')
                ->leftJoin('member_levels', 'shop_accounts.level', '=', 'member_levels.id')
                ->where('sales.create_time', '>=', $today)->where('sales.create_time', '<', $tomorrow)
                ->where('sales.zone', $zone)->where('sales.uid', $uid)
                ->select('shop_accounts.uid', 'shop_accounts.name', 'member_levels.level_name', 'sales.sale as day_sale')
                ->get()->toArray();
            $res['persons'] = $persons;
            $return['list'][] = $res;
        }
        return $return;
    }

    /**
     * 结算昨日的量碰奖励,默认当天奖励第二日结算，被废弃
     * @param int $uid
     * @return bool
     */
    public function clearYesTouchBonus(int $uid)
    {
//        $yeterday  = mktime(0, 0, 0, date("m")  , date("d") - 1, date("Y"));
//        $today = strtotime(date('Y-m-d'));
        // 排除当天已经结算过昨天的
//        $has = DB::table('money_report')->where('uid', $uid)->where('create_time', '>', $today)->where('types', 4)->count();
//        if ($has > 0) {
//            $this->error = '昨日量碰奖励已结算';
//            return false;
//        }
//        $bonus = $this->calculateTouchBonus($uid, $yeterday, $today);
        $bonus = $this->calculateTotalBonus($uid);
        if ($bonus == 0) return false;
        Log::info($uid.'量碰奖:￥'.$bonus);
        DB::table('money_report')->insert([
            'uid' => $uid,
            'types' => 4,
            'amount' => $bonus,
            'status' => 1,
//            'remark' => date('Y-m-d', strtotime('-1 day')) . '量碰奖励',
            'remark' => '量碰奖励',
            'create_time' => time()
        ]);
        return true;
    }

    /**
     * 计算一个时间段内的量碰收益
     * @param int $uid
     * @param int $beginTime
     * @param int $endTime
     * @return float|int|string
     */
    public function calculateTouchBonus(int $uid, int $beginTime, int $endTime = 0)
    {
        $touchBonus = 0;
        $touchChildren = (new Btree())->getLimitLRChildren($uid);
        // 统计能够碰撞的左区时间段内销售额
        $lTouchSale = $this->aggregateSales($touchChildren['lzone'], $beginTime, $endTime);
        // 优化查找。一区销售额为0，则量碰为0
        if ($lTouchSale <= 0) return $touchBonus;

        // 统计能够碰撞的右区时间段内销售额
        $rTouchSale = $this->aggregateSales($touchChildren['rzone'], $beginTime, $endTime);
        if ($rTouchSale <= 0) return $touchBonus;

        // 获取用户的量碰级别
        $touchSet = (new Setting())->getTouchSet();
        $pv = $touchSet['touch_pv'];
        $level = ShopAccount::where('uid', $uid)->value('level');
        foreach ($touchSet['touch_bonus_rules'] as $set) {
            if ($set['level_id'] == $level) {
                $touchBase = $set['touch_base'];
                $bonusRate = $set['bonus_rate'];
                $extraBonusRate = $set['extra_bonus_rate'];
                break;
            }
        }
        unset($touchSet);

        $base = $lTouchSale > $rTouchSale ? $rTouchSale : $lTouchSale;
        // 获取历史已获量碰收益
        $getTouchBonus = DB::table('money_report')->where('uid', $uid)->where('types', 4)->sum('amount');
        if ($getTouchBonus >= $touchBase) {
            $touchBonus = sprintf('%.2f', $base * $extraBonusRate * $pv / 100);
            return $touchBonus;
        }

        $rest = $touchBase - $getTouchBonus;
        $protected = sprintf('%.2f', $rest / $pv / $bonusRate * 100);
        if ($protected > $base) {
            $touchBonus = sprintf('%.2f', $base * $bonusRate * $pv / 100);
            return $touchBonus;
        }

        $touchBonus = ($base - $protected) * $extraBonusRate * $pv / 100 + $touchBase;
        $touchBonus = sprintf('%.2f', $touchBonus);
        return $touchBonus;
    }

    /**
     * 量碰金额累计结算
     * @param int $uid
     * @return int|string
     */
    public function calculateTotalBonus(int $uid)
    {
        $touchBonus = 0;
        $touchChildren = (new Btree())->getLimitLRChildren($uid);
        // 统计能够碰撞的左区时间段内销售额
        $lTouchSale = $this->aggregateSales($touchChildren['lzone']);
        // 优化查找。一区销售额为0，则量碰为0
        if ($lTouchSale <= 0) return $touchBonus;

        // 统计能够碰撞的右区时间段内销售额
        $rTouchSale = $this->aggregateSales($touchChildren['rzone']);
        if ($rTouchSale <= 0) return $touchBonus;

        // 获取用户的量碰级别
        $touchSet = (new Setting())->getTouchSet();
        $pv = $touchSet['touch_pv'];
        $level = ShopAccount::where('uid', $uid)->value('level');
        foreach ($touchSet['touch_bonus_rules'] as $set) {
            if ($set['level_id'] == $level) {
                $touchBase = $set['touch_base'];
                $bonusRate = $set['bonus_rate'];
                $extraBonusRate = $set['extra_bonus_rate'];
                break;
            }
        }
        unset($touchSet);

        $base = $lTouchSale > $rTouchSale ? $rTouchSale : $lTouchSale;
        // 获取历史已获量碰收益
        $getTouchBonus = DB::table('money_report')->where('uid', $uid)->where('types', 4)->sum('amount');
        $protectedBase = $touchBase / $bonusRate / $pv * 100;
        if ($base > $protectedBase) {
            $totalBonus = ($base - $protectedBase) * $extraBonusRate * $pv / 100 + $touchBase;
        } else {
            $totalBonus = $base * $bonusRate * $pv / 100;
        }
        $touchBonus = sprintf('%.2f', $totalBonus - $getTouchBonus);
        return $touchBonus;
    }


}